#include <yunpan.h>
#include"threadPool.h"
#include"head.h"
#include"taskQueue.h"
#include <mysql/mysql.h>

//连接mysql-----------------------------------------------------------------------
int connectToMysql(MYSQL **pmysql)
{
    *pmysql = mysql_init(NULL);
    char *host = "localhost";
    char *user = "root";
    char *password = "981229";
    char *database = "YunDataBase";
    MYSQL *ret = mysql_real_connect(*pmysql, host, user, password, database, 0, NULL, 0);
    if(ret != NULL)
    {
        printf("Connect to MySQL Successfully!\n");
    }
    else
    {
        printf("Error: %s\n", mysql_error(*pmysql));
    }
}

//用户登录------------------------------------------------------------------------

int getSalt(char *salt, char *serctNum)
{
    int i, j;
    for(i = 0, j = 0; serctNum[i] && j != 3; ++i)
    {
        if(serctNum[i] == '$')
        {
            ++j;
        }
    }
    strncpy(salt, serctNum, i - 1);
    return 0;
}

int checkUserPass(task_t *pTask, char *userName, char *password)
{   
    char *Salt;
    char *secretNum;
    char sql[1024] = {0}; 
    sprintf(sql, "select * from shadow where Name = '%s'", userName);
    int qret = mysql_query(pTask->pmysql, sql);
    if(qret != 0)
    {
        printf("Error: %s\n", mysql_error(pTask->pmysql));
    }
    MYSQL_RES *result = mysql_store_result(pTask->pmysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    Salt = row[2];
    secretNum = row[3];
    if(strcmp(secretNum, crypt(password, Salt)) == 0)
    {
        mysql_free_result(result);
        return 0;
    }
    else
    {
        mysql_free_result(result);
        return -1;
    }   
}

//创建新用户-----------------------------------------------------------------------

int addNewSalt(char *salt)
{   
    srand(time(NULL));
    int i, flag; 
    salt[0] = '$';
	salt[1] = '6';	
	salt[2] = '$';
    for(i = 0; i < 8; ++i)
    {
        flag = rand() % 3;
        switch(flag)
        {
            case 0:
                salt[i + 3] = rand() % 26 + 'a';
                break;
            case 1:
                salt[i + 3] = rand() % 26 + 'A';
                break;
            case 2:
                salt[i + 3] = rand() % 10 + '0';
                break;
        }
    }
    salt[11] = '$';
    return 0;
}

int addNewUser(task_t *pTask, char *userName, char *password)
{
    char salt[13] = {0};
    char secretNum[100] = {0};
    addNewSalt(salt);
    strcpy(secretNum, crypt(password, salt));
    char sql[1024] = {0};
    sprintf(sql, "insert into shadow (Name, Salt, Shadow) values ('%s', '%s','%s')"
            , userName, salt, secretNum);
    int qret = mysql_query(pTask->pmysql, sql);
    if(qret == 0)
    {
        printf("Create Success!\n");
        return 0;
    }
    else
    {
        printf("Error: %s\n", mysql_error(pTask->pmysql));
        return -1;
    }
}

//虚拟文件系统---------------------------------------------------------------------

//通过Name、User和Pre_idx获取Idx,pDir在传入前提前初始化
int getMyIdx(task_t *pTask, char **goalIdx)
{
    char sql[1024] = {0};
    sprintf(sql, "select * from dir where User = '%s' and Name = '%s' and Pre_idx = '%s'"
            , pTask->user, pTask->curDir->Name, pTask->curDir->Pre_idx);
    int qret = mysql_query(pTask->pmysql, sql);
    if(qret != 0)
        printf("Error: %s\n", mysql_error(pTask->pmysql));
    MYSQL_RES *result = mysql_store_result(pTask->pmysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    *goalIdx = row[0];
    return 0;
}

int newUserDir(task_t *pTask)
{
    char sql[1024] = {0};
    sprintf(sql, "insert into dir (Name, Type, User, Pre_idx, md5)  values ('%s', 'dir', '%s', '0', 'NULL')"
            , pTask->user, pTask->user);
    puts(sql);
    int qret = mysql_query(pTask->pmysql, sql);
    if(qret == 0)
    {
        printf("Create newUserDir Success!\n");
        return 0;
    }
    else
    {
        printf("Error: %s\n", mysql_error(pTask->pmysql));
        return -1;
    }
}

//--------------------------------------------------------------------------------

int makeWorker(threadPool_t *pThreadPool){
    for(int i =0;i < pThreadPool->threadNum;++i){
        pthread_create(pThreadPool->tidArr+1,NULL,threadFunc,(void*)pThreadPool);
    }
}

int OrderJudge(task_t * pTask){
    char buf[1024]={0};
    if(strncmp(pTask->buf,"cd ",3)==0){
        cd(pTask);
    }
    else if(strncmp(pTask->buf,"cd",2)==0){
        cd(pTask);
    }
    else if(strncmp(pTask->buf,"ls ",3)==0){
        ls(pTask);
    }
    else if(strncmp(pTask->buf,"ls",2)==0){
        ls(pTask);
    }
    else if(strncmp(pTask->buf,"puts ",5)==0){
       //cd(pTask);
       uploadFile(pTask);
    }
    else if(strncmp(pTask->buf,"gets ",5)==0){
        //puts("gets");
        downloadFile(pTask);
    }
    else if(strncmp(pTask->buf,"remove ",7)==0){
        //puts("remove");
        removeFile(pTask);
    }
    else if(strncmp(pTask->buf,"mkdir ",6)==0){
        mkNewDir(pTask);
    }
    else if(strncmp(pTask->buf,"rmdir ",6)==0){
        //removeFile(pTask);
        puts("rmdir");
    }
    else{
        send(pTask->netFd,"命令错误，重新输入！",30,0);
        return -1;
    }
}

void *threadFunc(void *parg){
    threadPool_t *pThreadPool = (threadPool_t *)parg; //地址传递传入传出参数
    while (1){
        task_t *pTask;//新建一个task来接收队首的任务
        pthread_mutex_lock(&pThreadPool->mutex);
        while (pThreadPool->taskQueue.size == 0){
            pthread_cond_wait(&pThreadPool->cond,&pThreadPool->mutex);//解锁了等一个信号
        }
        puts("GetTask");//来信号了自动上锁
        pTask = pThreadPool->taskQueue.pFront;
        deQueue(&pThreadPool->taskQueue);
        pthread_mutex_unlock(&pThreadPool->mutex);
        printf("netFd = %d\n",pTask->netFd);
        handleEvent(pTask);
    }
}

int handleEvent(task_t* pTask){
    task_t mypTask = *pTask; //接收下来
    puts("welcome into handEvent!");
    int netFd = mypTask.netFd;
    
    connectToMysql(&mypTask.pmysql);
    mypTask.curDir = (curDir_t*)malloc(sizeof(curDir_t));
    puts("here");
    char userName[20] = {0};
    char password[20] = {0};
    char enterOrAdd[3] = {0};
    int ret = recv(netFd, enterOrAdd, 3, 0);
    ERROR_CHECK(ret, -1, "recv enterOrAdd");
    if(strcmp(enterOrAdd,"2\n")==0)
    {
        int ret = recv(netFd, userName, sizeof(userName), 0);
        ret = recv(netFd, password, sizeof(password), 0);
        ret = addNewUser(&mypTask, userName, password);
        if(ret == 0)
        {
            
            send(netFd, "5", 2, 0);
            mypTask.user = userName;
            newUserDir(&mypTask);
            mypTask.curDir->Pre_idx = "0";
            mypTask.curDir->Name = userName;
            mypTask.curDir->Type = "dir";
            mypTask.curDir->md5 = "NULL";
            getMyIdx(&mypTask, &mypTask.curDir->Idx);
            
        }
        else
        {
            send(netFd, "-1", 3, 0);
        }
    }
    else if(strcmp(enterOrAdd,"1\n") == 0)
    {
        //从这开始是密码验证需要的，
        while(1)
        {
            recv(netFd, userName, sizeof(userName), 0);
            recv(netFd, password, sizeof(password), 0);
            puts(userName);
            puts("gets passwd");
            int ret = checkUserPass(&mypTask, userName, password);
            if(ret == 0)
            {
                
                send(netFd, "5", 2, 0);
                mypTask.user = userName;
                mypTask.curDir->Pre_idx = "0";
                mypTask.curDir->Name = userName;
                mypTask.curDir->Type = "dir";
                mypTask.curDir->md5 = "NULL";
                getMyIdx(&mypTask, &mypTask.curDir->Idx);
                break;
            }
            else if(ret == -1)
            {
                send(netFd, "-1", 3, 0);
                memset(userName, 0, sizeof(userName));
                memset(password, 0, sizeof(password));
                //循环再次输入
            }
        }
    }

    //usrConnectRecord(mypTask);//记录日志信息cat /var/log/syslog查看日志信息
    usrConnectRecord(mypTask);//记录登录时间
    while (1){
        bzero(mypTask.buf,sizeof(mypTask.buf));
        int ret = recv(mypTask.netFd,mypTask.buf,sizeof(mypTask.buf),0);
        if(ret == 0){
            puts("对面客户端断开！");
            break;
        }
        usrCommandRecord(mypTask);
        OrderJudge(&mypTask);
    }
    close(netFd);
    return 0;
} 
